package org.web.locks.databasedistributedlocks.server.biz.impl;

import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import org.web.base.domain.DeleteGroup;
import org.web.base.domain.exception.ResultMessageEnum;
import org.web.base.domain.helper.ServiceExceptionHelper;
import org.web.base.domain.helper.ValidationHelper;
import org.web.locks.databasedistributedlocks.sdk.biz.Locks;
import org.web.locks.databasedistributedlocks.sdk.dto.LockDTO;
import org.web.locks.databasedistributedlocks.sdk.dto.TryLockDTO;

import javax.annotation.Resource;

@Service("databaseDistributedLocks")
@Validated
public class DatabaseDistributedLocks implements Locks {

    @Resource
    private DistributedLocksServiceBizImpl distributedLocksServiceBiz;

    @Override
    public TryLockDTO tryLockDTO(TryLockDTO tryLockDTO) {
        String lockMarker = tryLockDTO.getLockDTO().getDistributedLocksId();
        Integer lockExpiryTime = tryLockDTO.getLockDTO().getLockExpiryTime();
        String lockOwner = tryLockDTO.getLockDTO().getLockOwner();
        Integer tryCount = tryLockDTO.getTryCount();
        Long tryTimeout = tryLockDTO.getTryTimeout();
        // 设置默认值
        if (tryTimeout == null) {
            tryTimeout = 0L; // 默认超时时间为 0 毫秒，即不等待
            tryLockDTO.setTryTimeout(tryTimeout);
        }

        if (tryCount == null) {
            tryCount = 1; // 默认尝试次数为 1 次
            tryLockDTO.setTryCount(tryCount);
        }

        if (lockExpiryTime == null) {
            lockExpiryTime = 5000;
            tryLockDTO.getLockDTO().setLockExpiryTime(lockExpiryTime);
        }

        // 如果只尝试一次获取锁，直接尝试并返回结果
        if (tryCount == 1) {
            tryLockDTO.setSuccess(distributedLocksServiceBiz.tryLock(lockMarker, lockExpiryTime, lockOwner));
            return tryLockDTO;
        }
        // 如果尝试次数大于1，则计算每次重试的等待时间 = 总超时时间 / (尝试次数 - 1)
        long sleepInterval = (tryCount > 1) ? tryTimeout / (tryCount - 1) : 0;

        for (int i = 0; i < tryCount; i++) {
            // 尝试获取锁
            boolean lockAcquired = distributedLocksServiceBiz.tryLock(lockMarker, lockExpiryTime, lockOwner);
            if (lockAcquired) {
                tryLockDTO.setSuccess(true);
                return tryLockDTO; // 如果成功获取锁，立即返回 true
            }

            // 如果未获取锁且还有重试次数，检查是否需要等待再重试
            if (i < tryCount - 1 && sleepInterval > 0) {
                try {
                    Thread.sleep(sleepInterval); // 等待指定的时间后重试
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt(); // 恢复中断状态
                    return tryLockDTO;
                }
            }
        }

        // 如果所有尝试都失败，返回 false
        return tryLockDTO;
    }

    @Override
    public boolean releaseLock(LockDTO lockDTO) {
        if (lockDTO == null) {
            throw ServiceExceptionHelper.buildServiceException(ResultMessageEnum.PARAM_EMPTY, "lockDTO 参数不能为空");
        }
        ValidationHelper.validateWithThrow(LockDTO.class, lockDTO, DeleteGroup.class);
        return distributedLocksServiceBiz.releaseLock(lockDTO.getDistributedLocksId(), lockDTO.getLockOwner());
    }
}
